﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using jQuery.WebControls.UI;
using System.Web.UI.HtmlControls;
using System.Collections;
using System.Drawing.Design;

namespace jQuery.WebControls
{
    /// <summary>
    /// Control to use mandatory controls jQuery.WebControls namespace. Add CSS and jQuery resources necessary for the proper
    /// operation of controls. 
    /// <para>Specifications are also common properties to all controls of various types, such as the Language of DateTextBox, format
    /// of numbers NumberTextBox, the style for all controls jQuery.WebControls.UI namespace, etc.</para>
    /// </summary>
    [DefaultProperty("DefaultCssUI")]
    [ToolboxData("<{0}:jQueryScriptManager runat=server></{0}:jQueryScriptManager>")]
    [Description("Control to use mandatory controls jQuery.WebControls namespace")]
    public class jQueryScriptManager : WebControl
    {        
        private bool[] neededSources;
        
        private enum Sources
        {            
            lightbox,
            rocketDock,
            numberFormatter,
            jqueryUI,
            dateTextBox,
            preloader
        }

        #region PROPIEDADES
        private bool[] NeedSource
        {
            get
            {
                if (neededSources == null)
                    neededSources = new bool[Enum.GetNames(typeof(Sources)).Length];
                return neededSources;
            }            
        }        
        /// <summary>
        /// Gets or sets the default style for all controls of the jQuery.WebControls.UI namespace
        /// </summary>
        [Category("Appearance")]
        [DefaultValue(DefaultStyle.Lightness)]
        [Description("Gets or sets the default style for all controls of the jQuery.WebControls.UI namespace")]
        public DefaultStyle DefaultCssUI
        {
            get
            {
                if (ViewState["css"] == null)
                {
                    ViewState.Add("css", DefaultStyle.Lightness);
                }
                return (DefaultStyle)ViewState["css"];
            }
            set
            {                
                ViewState["css"] = value;                
            }
        }

        /// <summary>
        /// Class name to apply the button style of DefaultCssUI
        /// </summary>
        [Category("Appearance")]
        [DefaultValue("")]
        [Description("Class name to apply the button style of jquery.ui")]
        public string CssClassButtons
        {
            get
            {
                return base.CssClass;
            }
            set
            {
                base.CssClass = value;
            }
        }
        #endregion

        #region NumberTextBox PROPERTIES
        /// <summary>
        /// Format of the local area in which you want to display the number
        /// </summary>        
        [Category("Appearance")]
        [DefaultValue(LocaleArea.Spain)]
        [Localizable(true)]
        [Description("Format of the local area in which you want to display the number")]
        public LocaleArea AreaLocal
        {
            get
            {
                if (ViewState["a"] == null)
                {
                    ViewState.Add("a", LocaleArea.Spain);
                }
                return (LocaleArea)Enum.Parse(typeof(LocaleArea), ViewState["a"].ToString());
            }
            set
            {
                ViewState["a"] = value;
            }
        }

        /// <summary>
        /// Symbol of the currency in which you want to represent the controls NumericTextBox
        /// </summary>        
        [Category("Appearance")]
        [DefaultValue("€")]
        [Localizable(true)]
        [Description("Symbol of the currency in which you want to represent the controls NumericTextBox")]
        public string CoinSymbol
        {
            get
            {
                if (ViewState["sy"] == null)
                {
                    ViewState.Add("sy", "€");
                }
                return ViewState["sy"].ToString();
            }
            set
            {
                ViewState["sy"] = value;
            }
        }
        
        /// <summary>
        /// Number of decimal places that should contain all the controls with numeric NumberTextBox equal percentage or currency
        /// </summary>
        [Category("Appearance")]
        [DefaultValue("2")]
        [Localizable(true)]
        [Description("Number of decimal places that should contain all the controls with numeric NumberTextBox equal percentage or currency")]
        public int NumericPrecision
        {
            get
            {
                if (ViewState["pre"] == null)
                {
                    ViewState.Add("pre", 2);
                }
                return int.Parse(ViewState["pre"].ToString());
            }
            set
            {
                ViewState["pre"] = value;
            }
        }

        /// <summary>
        /// Decimal separator to be used in all controls NumberTextBox
        /// </summary>
        [Category("Appearance")]
        [DefaultValue(".")]
        [Localizable(true)]
        [Description("Decimal separator to be used in all controls NumberTextBox")]
        public char DecimalSeparator
        {
            get
            {
                if (ViewState["ds"] == null)
                {
                    ViewState.Add("ds", '.');
                }
                return char.Parse(ViewState["ds"].ToString());
            }
            set
            {
                if (value.Equals('.') || value.Equals(','))
                {
                    if (value == ThousandSeparator)
                    {
                        throw new ArgumentException(jQuery.Messages.QSM_err1);
                    }
                    ViewState["ds"] = value;
                }
                else
                {
                    throw new ArgumentException(jQuery.Messages.QSM_err2);
                }                
            }
        }
        /// <summary>
        /// Thousands separator to be used in all controls NumberTextBox
        /// </summary>
        [Category("Appearance")]
        [DefaultValue(".")]
        [Localizable(true)]
        [Description("Thousands separator to be used in all controls NumberTextBox")]
        public char ThousandSeparator
        {
            get
            {
                if (ViewState["ts"] == null)
                {
                    ViewState.Add("ts", ' ');
                }
                return char.Parse(ViewState["ts"].ToString());
            }
            set
            {
                if (value.Equals('.') || value.Equals(','))
                {
                    if (value == DecimalSeparator)
                    {
                        throw new ArgumentException(jQuery.Messages.QSM_err4);
                    }
                    ViewState["ts"] = value;
                }
                else
                {
                    throw new ArgumentException(jQuery.Messages.QSM_err3);
                }               
            }
        }
        /// <summary>
        /// Error message to be displayed on all NumberTextBox controls when the text entered is not a number
        /// </summary>
        [Category("Appearance")]
        [DefaultValue("is an incorrect number")]
        [Localizable(true)]
        [Description("Error message to be displayed on all NumberTextBox controls when the text entered is not a number")]
        public string ErrorMessageIncorrectNumber 
        {
            get
            {
                if (ViewState["mssgErrNum"] == null)
                {
                    ViewState["mssgErrNum"] = "is an incorrect number";
                }
                return ViewState["mssgErrNum"].ToString();
            }
            set
            {
                ViewState["mssgErrNum"] = value;
            }
        }
        #endregion

        #region DateTextBox PROPERTIES
        /// <summary>
        /// Gets or sets how many months to move when clicking the Previous/Next links
        /// </summary>
        /// <exception cref="ArgumentException">StepMonths has to be an integer between 1 and 12</exception>
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("1")]
        [Localizable(true)]
        public int DatePickerStepMonths
        {
            get
            {
                if (ViewState["dpsm"] == null)
                {
                    ViewState["dpsm"] = 1;
                }
                return int.Parse(ViewState["dpsm"].ToString());
            }
            set
            {
                if (value > 0 && value < 13)
                {
                    ViewState["dpsm"] = value;
                }
                else
                {
                    throw new ArgumentException("StepMonths has to be an integer between 1 and 12");
                }
            }
        }
        /// <summary>
        /// Gets or sets the name of the animation used to show/hide the datepicker. Use 'show' (the default), 'slideDown', 'fadeIn', any of the show/hide jQuery UI effects, or '' for no animation
        /// </summary>
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("None")]
        [Localizable(true)]
        [Description("Gets or sets the name of the animation used to show/hide the datepicker. Use 'show' (the default), 'slideDown', 'fadeIn', any of the show/hide jQuery UI effects, or '' for no animation")]
        public Effect DatePickerShowAnimation
        {
            get
            {
                if (ViewState["dpsa"] == null)
                {
                    ViewState["dpsa"] = Effect.None;
                }
                return (Effect)Enum.Parse(typeof(Effect), ViewState["dpsa"].ToString());
            }
            set
            {
                ViewState["dpsa"] = value;
            }
        }

        /// <summary>
        /// Sets the language for the DateTextBox control 
        /// </summary>
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("Spanish")]
        [Localizable(true)]
        [Description("Sets the language for the DateTextBox control ")]
        public Language DatePickerLanguage
        {
            get
            {
                if (ViewState["Language"] == null)
                {
                    ViewState["Language"] = Language.Spanish;
                }
                return (Language)Enum.Parse(typeof(Language), ViewState["Language"].ToString());
            }
            set
            {
                ViewState["Language"] = value;
            }
        }

        /// <summary>
        /// If the required language for the calendar is not among the predefined js file you can specify the language amending Calendar
        /// </summary>
        [Category("Appearance")]
        [DefaultValue(""),
        Editor("System.Web.UI.Design.UrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
        [Description("If the required language for the calendar is not among the predefined js file you can specify the language amending Calendar")]
        public string DatePickerJsLanguagePath
        {
            get
            {
                String s = (String)ViewState["dpjs"];
                return ((s == null) ? "" : s);
            }
            set
            {
                ViewState["dpjs"] = value;
            }
        }


        /// <summary>
        /// Allows or denies to change the calendar year field with throught a DropDownList
        /// </summary>
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("false")]
        [Localizable(true)]
        [Description("Allows or denies to change the calendar year field with throught a DropDownList")]
        public bool ChangeYear
        {
            get
            {
                if (ViewState["chy"] == null)
                {
                    ViewState.Add("chy", false);
                }
                return bool.Parse(ViewState["chy"].ToString());
            }
            set
            {
                ViewState["chy"] = value;
            }
        }

        /// <summary>
        /// Allows or denies to change the calendar month field with throught a DropDownList
        /// </summary>
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("false")]
        [Localizable(true)]
        [Description("Allows or denies to change the calendar month field with throught a DropDownList")]
        public bool ChangeMonth
        {
            get
            {
                if (ViewState["chm"] == null)
                {
                    ViewState.Add("chm", false);
                }
                return bool.Parse(ViewState["chm"].ToString());
            }
            set
            {
                ViewState["chm"] = value;
            }
        }
        #endregion

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            
            CheckControls(Page.Controls);
                        
            ClientScriptProxy.RegisterClientScriptInclude(Page, GetType(), "jQueryMin",
                        ClientScriptProxy.GetWebResourceUrl(Page, GetType(), "jQuery.Resources.jquery_min.js"));
            if (NeedSource[Sources.preloader.GetHashCode()])
            {
                ClientScriptProxy.RegisterClientScriptInclude(Page, GetType(), "jQueryPreloader",
                    ClientScriptProxy.GetWebResourceUrl(Page, GetType(), "jQuery.Resources.jqueryLoader.js"));
            }
            if (NeedSource[Sources.lightbox.GetHashCode()])
            {
                ClientScriptProxy.RegisterClientScriptInclude(Page, GetType(), "jQueryLightbox",
                    ClientScriptProxy.GetWebResourceUrl(Page, GetType(), "jQuery.Resources.jquery_lightbox_0_5.js"));
            }
            if (NeedSource[Sources.rocketDock.GetHashCode()])
            {
                ClientScriptProxy.RegisterClientScriptInclude(Page, GetType(), "jQueryRocketDock",
                    ClientScriptProxy.GetWebResourceUrl(Page, GetType(), "jQuery.Resources.jquery_rocketdock.js"));
            }
            if (NeedSource[Sources.numberFormatter.GetHashCode()])
            {
                ClientScriptProxy.RegisterClientScriptInclude(Page, GetType(), "jQueryNumberFormatter",
                    ClientScriptProxy.GetWebResourceUrl(Page, GetType(), "jQuery.Resources.jquerynumberformatter_1_1_2.js"));                    
            }
            if (NeedSource[Sources.jqueryUI.GetHashCode()])
            {
                SetjQueryUI();
            }
            if (NeedSource[Sources.dateTextBox.GetHashCode()])
            {
                LoadDateTextBoxLanguage();
                string script = "";
                string option = "";
                if (DatePickerShowAnimation != Effect.None)
                    option = String.Format(", showAnim:'{0}'", DatePickerShowAnimation.ToString().ToLower());

                script = "$(function() {$('.DateTextBoxPicker').datepicker({stepMonths: " + DatePickerStepMonths.ToString() + ", changeMonth:" + ChangeMonth.ToString().ToLower() + ", changeYear:" + ChangeYear.ToString().ToLower() + option + "});});";
                ClientScriptProxy.RegisterClientScriptBlock(Page, GetType(), "DateTextBoxPicker", script, true);
            }            
            if (NeedSource[Sources.numberFormatter.GetHashCode()])
            {
               
                ClientScriptProxy.RegisterClientScriptBlock(Page, GetType(), "LoadNumberFormat",
                    ScriptLoadNumberFormat(), true);                               
            }            
            if (!String.IsNullOrEmpty(CssClassButtons))
            {
                if (!NeedSource[Sources.jqueryUI.GetHashCode()])
                {
                    SetjQueryUI();
                }
                ClientScriptProxy.RegisterStartupScript(Page, GetType(), 
                    "scButtons",
                    "$('." + CssClassButtons + "').button();", true);
            }                
            
        }

        private void SetjQueryUI()
        {
            ClientScriptProxy.RegisterClientScriptInclude(Page, GetType(), "jQueryUImin",
                    ClientScriptProxy.GetWebResourceUrl(Page, GetType(), "jQuery.Resources.jquery_ui_min.js"));
            Estilo x = new EstiloUI(Page, DefaultCssUI);
            x.ComprobarCSSenPagina();
        }

        private string ScriptLoadNumberFormat()
        {
            string optionsFNO = "{decimalSeparator: \"" + DecimalSeparator + "\", allowNegatives: false}";
            string cssInt, cssDbl, cssCoin, cssPercent, precision;
            cssInt = String.Format("{0}{1}", NumberTextBox.suffixCss, NumericFormat.Integer);
            cssDbl = String.Format("{0}{1}", NumberTextBox.suffixCss, NumericFormat.Double);
            cssCoin = String.Format("{0}{1}", NumberTextBox.suffixCss, NumericFormat.Coin);
            cssPercent = String.Format("{0}{1}", NumberTextBox.suffixCss, NumericFormat.Percentage);
            precision = "";
            for (int i = 0; i < NumericPrecision; i++)
            {
                precision += "#";
            }
            if (!string.IsNullOrEmpty(precision))
            {
                precision = "." + precision;
            }

            string script = "" +
            "$(\"." + cssDbl + "\").blur(function() {\n" +
            "$(this).format({ format: \"-#,###" + precision + "\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "});\n" +
            "$(\"." + cssDbl + "\").focus(function() {\n" +
            "$(this).parse({ locale: \"" + GetLocalFormat() + "\" });\n" +
            "$(this).format({ format: \"-" + precision + "\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "$(this).select();\n" +
            "});" +
            "$(\"." + cssDbl + "\").ForceNumericOnly(" + optionsFNO + ");\n" +
            "$(\"." + cssPercent + "\").blur(function() {\n" +
            "$(this).format({ symbol: \"%\", format: \"####" + precision + " %\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "});\n" +
            "$(\"." + cssPercent + "\").focus(function() {\n" +
            "$(this).parse({ symbol: \"%\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "$(this).format({symbol: \"%\", format: \"" + precision + "\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "$(this).select();\n" +
            "});\n" +
            "$(\"." + cssPercent + "\").ForceNumericOnly(" + optionsFNO + ");\n" +
            "$(\"." + cssInt + "\").blur(function() {\n" +
            "$(this).format({ format: \"0\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "});\n" +
            "$(\"." + cssInt + "\").focus(function() {\n" +
            "$(this).parse({ locale: \"" + GetLocalFormat() + "\" });\n" +
            "$(this).format({ format: \"0\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "$(this).select();\n" +
            "});" +
            "$(\"." + cssInt + "\").ForceNumericOnly(" + optionsFNO + ");\n" +
            "$(\"." + cssCoin + "\").blur(function() {\n" +
            "$(this).format({ symbol:\"" + CoinSymbol + "\", format: \"" + CoinSymbol + " #,###" + precision + "\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "});" +
            "\n" +
            "$(\"." + cssCoin + "\").focus(function() {\n" +
            "$(this).parse({ symbol:\"" + CoinSymbol + "\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "$(this).format({ symbol:\"" + CoinSymbol + "\", format: \"" + precision + "\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "$(this).select();\n" +
            "});$(\"." + cssCoin + "\").ForceNumericOnly(" + optionsFNO + ");\n" +
            "\n";
            script += "" +
            "   $(\"." + cssDbl + "\").format({ format: \"-#,###" + precision + "\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "   $(\"." + cssInt + "\").format({ format: \"0\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "   $(\"." + cssCoin + "\").format({ symbol:\"" + CoinSymbol + "\", format: \"" + CoinSymbol + " #,###" + precision + "\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "   $(\"." + cssPercent + "\").format({ symbol: \"%\", format: \"####" + precision + " %\", locale: \"" + GetLocalFormat() + "\" });\n" +
            "\n";

            script += "$(\"." + NumberTextBox.allowNegatives + "\").ForceNumericOnly({decimalSeparator: \"" + DecimalSeparator + "\", allowNegatives: true});";

            return "$(document).ready(function (){" + script + "});";
        }

        private string GetLocalFormat()
        {
            string aux;
            switch (AreaLocal)
            {
                case LocaleArea.GreatBritain:
                    aux = "gb";
                    break;
                case LocaleArea.Spain:
                    aux = "es";
                    break;
                default:
                    return "es";

            }
            return aux;
        }
        /// <summary>
        /// Returns the ClientScriptProxy to analyze if using Ajax Control Toolkit to correctly record the events
        /// </summary>
        public ClientScriptProxy ClientScriptProxy
        {
            get
            {               
                return ClientScriptProxy.Current;
            }
        }

        private void CheckControls(ControlCollection cc)
        {            
            for (int i = 0; i < cc.Count; i++)
            {
                if (cc[i].HasControls())
                {
                    CheckControls(cc[i].Controls);
                }
                CheckNeededResources(cc[i].GetType());
            }            
        }

        private void CheckNeededResources(Type tipo)
        {
            if (tipo.Namespace.Equals("jQuery.WebControls.ImageGallery"))
            {
                NeedSource[Sources.lightbox.GetHashCode()] = true;
            }
            else if (tipo.Namespace.Equals("jQuery.WebControls.RocketDock"))
            {
                NeedSource[Sources.rocketDock.GetHashCode()] = true;
            }
            else if (tipo.FullName.Equals("jQuery.WebControls.NumberTextBox"))
            {
                NeedSource[Sources.numberFormatter.GetHashCode()] = true;
            }            
            else if (tipo.Namespace.Equals("jQuery.WebControls.UI"))
            {
                NeedSource[Sources.jqueryUI.GetHashCode()] = true;
                if (tipo.FullName.Equals("jQuery.WebControls.UI.DateTextBox"))
                {
                    NeedSource[Sources.dateTextBox.GetHashCode()] = true;
                }
            }
            else if (tipo.FullName.Equals("jQuery.WebControls.Preloader"))
            {
                NeedSource[Sources.preloader.GetHashCode()] = true;
            }
        }

        /// <summary>
        /// Carga el Language del calendario para todos los DateTextBox de la página
        /// </summary>
        private void LoadDateTextBoxLanguage()
        {
            if (String.IsNullOrEmpty(DatePickerJsLanguagePath))
            {
                if (DatePickerLanguage == Language.Spanish)
                {
                    ClientScriptProxy.RegisterClientScriptInclude(this, GetType(), "jSpanishCalendar",
                        ClientScriptProxy.GetWebResourceUrl(Page, GetType(), "jQuery.Resources.jqueryuidatepicker_es.js"));
                }
                else if (DatePickerLanguage == Language.English)
                {
                    ClientScriptProxy.RegisterClientScriptInclude(this, GetType(), "jBritishCalendar",
                        ClientScriptProxy.GetWebResourceUrl(Page, GetType(), "jQuery.Resources.jqueryuidatepicker_en_GB.js"));
                }
                else if (DatePickerLanguage == Language.French)
                {
                    ClientScriptProxy.RegisterClientScriptInclude(this, GetType(), "jFrenchCalendar",
                        ClientScriptProxy.GetWebResourceUrl(Page, GetType(), "jQuery.Resources.jqueryuidatepicker_fr.js"));
                }
                else if (DatePickerLanguage == Language.German)
                {
                    ClientScriptProxy.RegisterClientScriptInclude(this, GetType(), "jGermanCalendar",
                        ClientScriptProxy.GetWebResourceUrl(Page, GetType(), "jQuery.Resources.jqueryuidatepicker_de.js"));
                }
                else if (DatePickerLanguage == Language.Italian)
                {
                    ClientScriptProxy.RegisterClientScriptInclude(this, GetType(), "jItalianCalendar",
                        ClientScriptProxy.GetWebResourceUrl(Page, GetType(), "jQuery.Resources.jqueryuidatepicker_it.js"));
                }
                else if (DatePickerLanguage == Language.Dutch)
                {
                    ClientScriptProxy.RegisterClientScriptInclude(this, GetType(), "jDutchCalendar",
                        ClientScriptProxy.GetWebResourceUrl(Page, GetType(), "jQuery.Resources.jqueryuidatepicker_nl.js"));
                }
                else if (DatePickerLanguage == Language.Polish)
                {
                    ClientScriptProxy.RegisterClientScriptInclude(this, GetType(), "jPolishCalendar",
                        ClientScriptProxy.GetWebResourceUrl(Page, GetType(), "jQuery.Resources.jqueryuidatepicker_pl.js"));
                }
            }
            else
            {
                ClientScriptProxy.RegisterClientScriptInclude(this, GetType(), "jUserDefineCalendar", 
                    ResolveClientUrl(DatePickerJsLanguagePath));
            }
        }

        /// <summary>
        /// This method is overload
        /// </summary>
        /// <param name="writer"></param>
        public override void RenderControl(HtmlTextWriter writer)
        {
            //base.RenderControl(writer);
        }
                
    }
}
